/*
 * sys.c
 *
 * Licenced under LGPL, ie. you can use the lib without legal notice or
 * hassle, but changes to this lib fall under GPL. Copyright (C) 
 * ID Software
 *
 * currently all system dependent shit is seperated from eachother
 * using conditional compilation. This must change into a sys_win32.c
 * and a sys_bsd.c and a sys_whatever.c
 * 
 * $Id: sys.c,v 1.1 2001/06/20 09:56:14 bsod Exp $
 */

#include <lobi/sys_floattime.h>
#include <assert.h>

/* get the current time as a double. from q1 */
#ifdef PORTABLE
#include <sys/time.h>
double Sys_FloatTime (void)
{
	struct timeval tp;
	struct timezone tzp; 
	static int      secbase;			/* not initialized ???? */

	gettimeofday(&tp, &tzp);  

	if (!secbase)
	{
		secbase = tp.tv_sec;
		return tp.tv_usec/1000000.0;
	}

	return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0;
}
#else
#include <windows.h>

// initialize these with Sys_FloatTimeInit()
static double curtime = 0.0, lastcurtime = 0.0;
static int lowshift;
static double pfreq;

#pragma warning (disable:4700)
void Sys_FloatTimeInit(void)
{
	LARGE_INTEGER	PerformanceFreq;
	unsigned int	lowpart, highpart;

	assert (QueryPerformanceFrequency (&PerformanceFreq));

	lowpart = (unsigned int)PerformanceFreq.LowPart;
	highpart = (unsigned int)PerformanceFreq.HighPart;
	lowshift = 0;

	while (highpart || (lowpart > 2000000.0))
	{
		lowshift++;
		lowpart >>= 1;
		lowpart |= (highpart & 1) << 31;
		highpart >>= 1;
	}

	pfreq = 1.0 / (double)lowpart;

	Sys_FloatTime();

	curtime = 0.0f;
	lastcurtime = curtime;
}

double Sys_FloatTime (void)
{
	static int			sametimecount;
	static unsigned int	oldtime;
	static int			first = 1;
	LARGE_INTEGER		PerformanceCount;
	unsigned int		temp, t2;
	double				time;


	QueryPerformanceCounter (&PerformanceCount);

	temp = ((unsigned int)PerformanceCount.LowPart >> lowshift) |
		   ((unsigned int)PerformanceCount.HighPart << (32 - lowshift));

	if (first)
	{
		oldtime = temp;
		first = 0;
	}
	else
	{
	// check for turnover or backward time
		if ((temp <= oldtime) && ((oldtime - temp) < 0x10000000))
		{
			oldtime = temp;	// so we can't get stuck
		}
		else
		{
			t2 = temp - oldtime;

			time = (double)t2 * pfreq;
			oldtime = temp;

			curtime += (float)time;

			if (curtime == lastcurtime)
			{
				sametimecount++;

				if (sametimecount > 100000)
				{
					curtime += 1.0;
					sametimecount = 0;
				}
			}
			else
			{
				sametimecount = 0;
			}

			lastcurtime = curtime;
		}
	}


	return curtime;
}
#endif
